package server

import (
	"fmt"
	"github.com/go-kratos/kratos/cmd/kratos/v2/internal/wire"
	"github.com/go-kratos/kratos/cmd/kratos/v2/util"
	"os"
	"path/filepath"
	"strings"
)

func (o *Object) usecase() error {

	for _, service := range o.Services {
		if err := o.genUsecase(service); err != nil {
			return err
		}
	}

	return nil
}

func (o *Object) genUsecase(s *Service) error {
	lowname := strings.ToLower(s.Service)
	filename := filepath.Join(o.rootPath, UsecasePath+"/"+lowname+".go")
	flag, err := util.PathExists(filename)
	if err != nil {
		return err
	}

	if !flag {
		body := fmt.Sprintf(usecaseTmp, o.rootPkg, s.Service, s.Service, s.Service, s.Service)
		body += o.usecaseBody(s, nil)

		err = os.WriteFile(filename, []byte(body), 0o644)
		if err != nil {
			return err
		}
		wireFilename := filepath.Join(o.rootPath, UsecasePath+"/wire.go")
		return wire.Gen(wireFilename, fmt.Sprintf("New%sUsecase", s.Service), UsecaseFile)
	}

	// 不存在的时候

	var isExistsNew bool
	methods := make(map[string]struct{})
	content, err := util.AddContentToFile(filename, "all", func(raw string) {
		arrs := strings.Split(raw, fmt.Sprintf("func (s *%sUsecase)", s.Service))
		if len(arrs) == 1 {
			return
		}
		idx := strings.Index(arrs[1], "(")
		if idx == -1 {
			return
		}

		m := strings.Trim(arrs[1][:idx], " ")
		methods[m] = struct{}{}
	}, func(positionStartIdx, positionEndIdx int, contents []string) []string {
		body := o.usecaseBody(s, methods)
		if len(body) == 0 {
			return contents
		}

		// 在接口处添加内容
		contents = append(contents, body)

		isExistsNew = true
		return contents
	})
	if err != nil || !isExistsNew {
		return err
	}

	os.Remove(filename)
	return os.WriteFile(filename, []byte(content), 0o644)
}

func (o *Object) usecaseBody(s *Service, filter map[string]struct{}) string {
	var res string
	for _, method := range s.Methods {
		if filter != nil {
			if _, ok := filter[method.Name]; ok {
				continue
			}
		}
		res += fmt.Sprintf(usecaseFuncTmp, s.Service, method.Name, method.Request, method.Reply, method.Reply)
	}
	return res
}
